package com.artfii.fluentsql.core;

import com.artfii.fluentsql.core.tools.StringKit;
import com.artfii.fluentsql.core.tools.Throw;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;

/**
 * Func:   :
 *
 * @author : Lqf(leeton)
 * @date : 2021/11/3.
 */
public class QueryKit {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //时间日期统一用这种格式

    private static final String hack_str = "/(\\\\%27)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|union|update|delete|trancate|" +
            "declare|exec|execute|insert into|drop|information_schema.columns|table_schema)\\b)";

    private static final Pattern SQL_HACK_PATTERN = Pattern.compile(hack_str, Pattern.CASE_INSENSITIVE);

    public static String settingParams(String symbolsql, Map<String, Object> params,boolean checkHack) {
        for (String key : params.keySet()) {
            String v = "";
            if (!isFieldVal(key, params.get(key))) {// key/val 都没有带别名,才转换了.
                v = changeValOfType(params.get(key));
            }else {
                v = (String)params.get(key);
            }
            Throw.isTrue(isSQLHack(v, checkHack), "WARN FIND SQL HACK ==> key:" + key + " ,param:" + v +"\n" +" [SQL]: "+symbolsql);
            symbolsql = StringKit.replace(symbolsql, key, v);
        }
        return symbolsql;
    }

    public static String changeValOfType(Object val) {
        if (null == val) return "";
        StringBuffer v = new StringBuffer(20);
        if (val instanceof String && isNotSubSelect(val)) {
            v.append("'").append(val).append("'");
            return v.toString();
        }
        //
        if (val instanceof Date || val instanceof Timestamp) {
            v.append("'").append(sdf.format(val)).append("'");
            return v.toString();
        }
        if (val instanceof BigDecimal) {
            v.append("'").append(((BigDecimal) val).doubleValue()).append("'");
            return v.toString();
        }
        if (val instanceof AtomicInteger) {
            v.append("'").append(((AtomicInteger) val).get()).append("'");
            return v.toString();
        }
        if (val instanceof AtomicLong) {
            v.append("'").append(((AtomicLong) val).get()).append("'");
            return v.toString();
        }
        //列表或数组
        v.append(StringKit.listOrArrayToLine(val));
        return v.toString();
    }

    public static boolean isSQLHack(String v,boolean checkSqlHack) {
        if (checkSqlHack) {
            return SQL_HACK_PATTERN.matcher(v).find();
        }
        return false;
    }


    private static boolean isFieldVal(String key, Object v) {
        return (key.indexOf(".") != -1 && v instanceof String && v.toString().indexOf(".") != -1);
    }

    private static boolean isNotSubSelect(Object v) {
        return !(("" + v).toUpperCase().startsWith("(SELECT"));
    }


    public static boolean isJavaNumberType(Object clz) {
        if (clz instanceof Integer
                || clz instanceof Long
                || clz instanceof Double
                || clz instanceof Float
                || clz instanceof BigDecimal
                || clz instanceof AtomicLong
                || clz instanceof AtomicInteger
                ){
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        String sql = "my name DELETE.";
        System.err.println("find sql hack:"+isSQLHack(sql, true));
    }


}
